<script setup lang="ts">
	import {ref, reactive, onMounted, computed} from 'vue';
	import {onLoad, onHide, onUnload} from '@dcloudio/uni-app';
	import _ from 'lodash';
	import apiOrder from '@/util/network_api/apiOrder.js';
	import apiUpload from '@/util/network_api/upload.js';
	import TextLength from '@/components/TextLength.vue';
	import {moduleId as fixedModuleId} from '@/config/order';
	import {
		useGetOrderEndTemplate,
		useGetEndInfo,
		useGetAllOrderModule,
		useSaveEndTemplate,
	} from '@/services/module/order/useOrder';
	import {Template, Field} from './types/end-order-apply';
	import CustomMultipleSelectModal from '@/components/common/multiple-select-modal/index.vue';

	defineOptions({
		name: 'OrderApplyEnd',
	});

	const {endTemplate, getEndTemplate, switchTemplate} =
		useGetOrderEndTemplate();
	const {endInfo, getEndInfo} = useGetEndInfo();
	const {getModuleListParam, moduleList, getModuleList} =
		useGetAllOrderModule();
	const {form, save} = useSaveEndTemplate();

	// 是否已经提交了，提交了就不能修改工单类型了
	const isSubmited = ref(false);

	// 工单类型 - 用于切换结单模板
	const orderModule = ref('');

	// 视频预览地址
	const videoPreviewUrl = ref('');

	// 模板列表
	const templateList = ref<Array<Template>>([]);

	/**
	 * 模块下拉列表
	 */
	const moduleOptions = computed(() => {
		return moduleList.value.map((module) => {
			return {
				value: module.id,
				text: module.name,
			};
		});
	});

	// 工单id
	const orderId = ref('');

	// 部门id
	const departmentId = ref('');

	/**
	 * 文件上传策略对象
	 */
	const fileUploadStrategy = {
		video: (param: {
			field: Field;
			templateIndex: number;
			fieldIndex: number;
		}) => {
			const {field, templateIndex, fieldIndex} = param;
			uni.chooseVideo({
				count: field.uploadQty - field.fileList.length,
				success: (res) => {
					addFile({
						templateIndex,
						fieldIndex,
						file: {
							path: res.tempFilePath,
						},
						url: res.tempFilePath,
					});
				},
			});
		},
		img: (param: {field: Field; templateIndex: number; fieldIndex: number}) => {
			const {field, templateIndex, fieldIndex} = param;
			uni.chooseImage({
				count: field.uploadQty - field.fileList.length,
				success: (res) => {
					res.tempFiles.forEach((tempFile) => {
						if (tempFile.size / 1024 / 1024 > field.uploadSize) {
							uni.showModal({
								title: '提示',
								content: `图片大小不能大于${field.uploadSize}MB!`,
							});
						} else {
							addFile({
								templateIndex,
								fieldIndex,
								file: tempFile,
								url: tempFile.path,
							});
						}
					});
				},
			});
		},
	};

	/**
	 * 文件预览策略对象
	 */
	const filePreviewStrategy = {
		img: (field: Field, fileIndex: number) => {
			uni.previewImage({
				urls: field.fileList.map((file) => file.url),
				current: fileIndex,
			});
		},
		video: (field: Field, fileIndex: number) => {
			const file = field.fileList[fileIndex];
			if (file) {
				videoPreviewUrl.value = file.url;
				showVideoPreviewPopup();
			}
		},
	};

	// 视频预览弹出层显示状态
	const videoPreviewPopupInstance = ref();

	/**
	 * 显示视频预览弹窗
	 */
	const showVideoPreviewPopup = () => {
		if (videoPreviewPopupInstance.value) {
			videoPreviewPopupInstance.value.open();
		}
	};

	/**
	 * 添加文件
	 * @param {object} param - 添加参数
	 * @param {number} param.templateIndex - 模板索引
	 * @param {number} param.fieldIndex - 字段索引
	 * @param {File} param.file - 文件对象
	 * @param {string} param.url - 文件预览路径
	 */
	const addFile = (param: {
		templateIndex: number;
		fieldIndex: number;
		url: string;
		file: File;
	}) => {
		const {templateIndex, fieldIndex, file, url} = param;
		templateList.value[templateIndex].content[fieldIndex].fileList.push({
			file,
			url,
		});
	};

	/**
	 * 根据模板索引和字段索引寻找字段
	 * @param {number} templateIndex - 模板索引
	 * @param {number} fieldIndex - 字段索引
	 */
	const findFieldByTemplateIndexAndFieldIndex = (
		templateIndex: number,
		fieldIndex: number,
	) => {
		const template = templateList.value[templateIndex];
		if (!template) {
			return false;
		}

		const field = template.content[fieldIndex];
		if (!field) {
			return false;
		}

		return field;
	};

	/**
	 * 文件上传点击事件
	 * @param {number} templateIndex - 模板索引
	 * @param {number} fieldIndex - 字段索引
	 */
	const handleFileUploadClick = (templateIndex: number, fieldIndex: number) => {
		const field = findFieldByTemplateIndexAndFieldIndex(
			templateIndex,
			fieldIndex,
		);
		if (!field) {
			return false;
		}

		let strategyKey = '';
		if (field.type === 5) {
			strategyKey = 'img';
		}

		if (field.type === 7) {
			strategyKey = 'video';
		}

		fileUploadStrategy[strategyKey]({
			templateIndex,
			fieldIndex,
			field,
		});
	};

	/**
	 * 文件删除事件
	 * @param {number} templateIndex - 模板索引
	 * @param {number} fieldIndex - 字段索引
	 * @param {number} fileIndex - 文件索引
	 */
	const handleFileDel = (
		templateIndex: number,
		fieldIndex: number,
		fileIndex: number,
	) => {
		const field = findFieldByTemplateIndexAndFieldIndex(
			templateIndex,
			fieldIndex,
		);
		if (!field) {
			return false;
		}

		templateList.value[templateIndex].content[fieldIndex].fileList.splice(
			fileIndex,
			1,
		);
	};

	/**
	 * 文件预览事件
	 * @param {number} templateIndex - 模板索引
	 * @param {number} fieldIndex - 字段索引
	 * @param {number} fileIndex - 文件索引
	 */
	const handleFilePreview = (
		templateIndex: number,
		fieldIndex: number,
		fileIndex: number,
	) => {
		const field = findFieldByTemplateIndexAndFieldIndex(
			templateIndex,
			fieldIndex,
		);
		if (!field) {
			return false;
		}

		if (field.type === 5) {
			filePreviewStrategy['img'](field, fileIndex);
		}

		if (field.type === 7) {
			filePreviewStrategy['video'](field, fileIndex);
		}
	};

	/**
	 * 文件列表初始化
	 */
	const fileListInit = () => {
		templateList.value = endTemplate.value.objects.map((template) => {
			template.content = template.content.map((field) => {
				field.fileList = [];
				return field;
			});
			return template;
		});
	};

	/**
	 * 下拉选择初始化
	 */
	const selectOptionsInit = () => {
		try {
			templateList.value = endTemplate.value.objects.map((template) => {
				template.content = template.content.map((field) => {
					if (field.choices) {
						const options = JSON.parse(field.choices);
						field.selectOptions = options.map((option) => {
							return {
								text: option.val,
								value: option.id,
							};
						});
					}
					return field;
				});
				return template;
			});
		} catch (error) {
			// error
		}
	};

	/**
	 * 评分初始化
	 */
	const rateInit = () => {
		try {
			templateList.value = endTemplate.value.objects.map((template) => {
				template.content = template.content.map((field) => {
					if (field.type === 8) {
						field.value = Number(field.value) || 0;
					}
					return field;
				});
				return template;
			});
		} catch (error) {
			// error
		}
	};

	/**
	 * 文件初始化
	 */
	const fileInit = () => {
		try {
			templateList.value = endTemplate.value.objects.map((template) => {
				template.content = template.content.map((field) => {
					if ([5, 7].includes(field.type)) {
						field.fileList = JSON.parse(field.value).map((item) => {
							return {
								file: null,
								url: item,
							};
						});
					}
					return field;
				});
				return template;
			});
		} catch (error) {
			// error
		}
	};

	/**
	 * 多选初始化
	 */
	const multipleSelectInit = () => {
		try {
			templateList.value = endTemplate.value.objects.map((template) => {
				template.content = template.content.map((field) => {
					if (field.type === 4) {
						if (field.value) {
							field.value = JSON.parse(field.value);
						} else {
							field.value = [];
						}
					}
					return field;
				});
				return template;
			});
		} catch (error) {
			// error
		}
	};

	/**
	 * 模板初始化
	 */
	const templateInit = () => {
		fileListInit();
		selectOptionsInit();
		rateInit();
		fileInit();
		multipleSelectInit();
	};

	/**
	 * 页面初始化
	 */
	const init = () => {
		getEndTemplate(orderId.value).then(() => {
			templateInit();
		});
		getEndInfo(orderId.value);

		getModuleListParam.value.departmentId = departmentId.value;
		getModuleList(0);
	};

	/**
	 * 提交事件
	 */
	const onSubmit = async () => {
		form.value.length = 0;
		form.value = _.cloneDeep(templateList.value);
		// 模板列表
		for (
			let templateIndex = 0;
			templateIndex < form.value.length;
			templateIndex++
		) {
			// 模板对象
			const template = form.value[templateIndex];

			// 字段列表
			for (
				let fieldIndex = 0;
				fieldIndex < template.content.length;
				fieldIndex++
			) {
				// 字段对象
				const field = template.content[fieldIndex];

				// 文件上传
				if ([5, 7].includes(field.type)) {
					field.value = [];
					for (
						let fileIndex = 0;
						fileIndex < field.fileList.length;
						fileIndex++
					) {
						if (field.fileList[fileIndex].file) {
							const uploadFn =
								field.type === 5
									? apiUpload.uploadOrderFile
									: apiUpload.orderVideoUpload;
							const res = await uploadFn({
								files: field.fileList[fileIndex].file,
							});
							if (res.code === 20000) {
								field.fileList[fileIndex].url = res.data.rows[0];
							}
						}
					}
					field.value = field.fileList.map((item) => item.url);
				}

				if ([3, 4].includes(field.type)) {
					delete field.selectOptions;
				}

				if ([4, 5, 7].includes(field.type)) {
					field.value = JSON.stringify(field.value);
				}
			}
		}

		const res = await save(orderModule.value, orderId.value);
		if (res.code === 20000) {
			uni.navigateTo({
				url: `/pages_network/order/detail?workId=${orderId.value}`,
			});
			return;
		}
		uni.showModal({
			title: '提示',
			content: res.message,
		});
	};

	/**
	 * 处理隐藏手机号
	 * @param {string} phone - 手机号
	 */
	const hidePhone = (phone: string) => {
		if (!phone) {
			return '';
		}

		return phone.slice(0, 3) + '****' + phone.slice(phone.length - 4);
	};

	/**
	 * 工单类型选择事件
	 */
	const handleOrderModuleChange = async () => {
		await switchTemplate(orderModule.value, orderId.value);
		templateInit();
	};

	onLoad((e) => {
		if (!e || !e.workId || !e.departmentId || !e.moduleId || !e.status) {
			return;
		}

		orderId.value = e.workId;
		departmentId.value = e.departmentId;
		orderModule.value = e.moduleId;
		isSubmited.value = Number(e.status) === 1;
		init();
	});
</script>

<template>
	<view class="apply-end-container">
		<view class="content">
			<view class="info">
				<view class="info-item">
					<view class="order-no">{{ endInfo.workNo }}</view>
					<view class="order-module">
						{{ endInfo.module }}
					</view>
				</view>
				<div class="info-item">
					<view class="label">客户信息：</view>
					<view class="value" v-if="endInfo.userPhone">
						{{ endInfo.username }}&nbsp;{{ hidePhone(endInfo.userPhone) }}
					</view>
				</div>
				<div class="info-item">
					<view class="label">报单时间：</view>
					<view class="value">
						{{ endInfo.createTime }}
					</view>
				</div>
				<view class="info-item">
					<view class="label">工单描述：</view>
					<view class="value">
						<TextLength :text="endInfo.content || '-'"></TextLength>
					</view>
				</view>
			</view>
			<view class="template-list">
				<view class="order-module">
					<view class="label">工单类型：</view>
					<uni-data-select
						:localdata="moduleOptions"
						placeholder="请选择工单类型"
						v-model="orderModule"
						@change="handleOrderModuleChange"
						:disabled="isSubmited"
						style="width: 100%"
					></uni-data-select>
				</view>
				<view
					class="template"
					v-for="(template, templateIndex) in templateList"
					:key="templateIndex"
				>
					<view class="title">{{ template.templateName }}</view>
					<view class="field-list">
						<view
							class="field"
							v-for="(field, fieldIndex) in template.content"
							:key="fieldIndex"
						>
							<view class="field-content">
								<view class="label">{{ field.property }}</view>
								<view class="value">
									<!-- 单行输入、多行输入 -->
									<input
										type="text"
										v-if="[1, 2].includes(field.type)"
										:placeholder="field.tip || '请输入内容'"
										class="input"
										placeholder-style="text-align: right;"
										v-model="field.value"
									/>

									<!-- 评分 -->
									<uni-rate
										v-if="field.type === 8"
										v-model="field.value"
									></uni-rate>

									<!-- 日期 -->
									<uni-datetime-picker
										type="date"
										v-if="field.type === 9"
										:border="false"
										v-model="field.value"
									/>

									<!-- 日期 -->
									<uni-datetime-picker
										type="datetime"
										v-if="field.type === 10"
										:border="false"
										v-model="field.value"
									/>

									<!-- 下拉单选 -->
									<view v-if="field.type === 3" class="select">
										<uni-data-select
											v-model="field.value"
											:localdata="field.selectOptions"
										></uni-data-select>
									</view>

									<!-- 下拉多选 -->
									<view v-if="field.type === 4" class="multiple-select">
										<custom-multiple-select-modal
											:options="field.selectOptions"
											v-model="field.value"
										/>
									</view>

									<!-- 图片\视频上传 -->
									<view
										v-if="[5, 7].includes(field.type)"
										class="file-upload"
										@click="handleFileUploadClick(templateIndex, fieldIndex)"
									>
										点击上传
									</view>
								</view>
							</view>
							<view class="file-list" v-if="field.fileList.length > 0">
								<view
									class="file"
									v-for="(file, fileIndex) in field.fileList"
									:key="fileIndex"
								>
									<image
										:src="file.url"
										v-if="field.type === 5"
										class="img"
										@click="
											handleFilePreview(templateIndex, fieldIndex, fileIndex)
										"
									></image>
									<video
										:src="file.url"
										v-if="field.type === 7"
										class="video"
										:show-center-play-btn="false"
										:show-play-btn="false"
										:controls="false"
										@click="
											handleFilePreview(templateIndex, fieldIndex, fileIndex)
										"
									></video>

									<view
										class="del-btn"
										@click="handleFileDel(templateIndex, fieldIndex, fileIndex)"
									>
										<uni-icons
											type="closeempty"
											size="12"
											color="#fff"
										></uni-icons>
									</view>
								</view>
							</view>
						</view>
					</view>
				</view>
			</view>
		</view>
		<view class="btn-container">
			<button type="primary" class="btn_bor" @click="onSubmit">提交</button>
		</view>

		<uni-popup ref="videoPreviewPopupInstance">
			<view class="video-preview-container">
				<video :src="videoPreviewUrl"></video>
			</view>
		</uni-popup>
	</view>
</template>

<style lang="scss" scoped>
	.video-preview-container {
		width: 600rpx;
		height: 450rpx;
	}

	.apply-end-container {
		background-color: #fafafa;
		/* #ifdef H5 */
		height: calc(100vh - 88rpx);
		/* #endif */
		/* #ifndef H5 */
		height: 100vh;
		/* #endif */
		overflow-y: auto;
		display: flex;
		flex-direction: column;

		.content {
			margin: 24rpx;
			flex: 1;
			height: 0;
			display: flex;
			flex-direction: column;
			row-gap: 24rpx;

			.info {
				display: flex;
				flex-direction: column;
				row-gap: 12rpx;
				background-color: #fff;
				box-sizing: border-box;
				padding: 24rpx;
				border-radius: 8rpx;
				box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.05);

				.info-item {
					display: flex;
					font-size: 24rpx;
					justify-content: space-between;

					.order-module {
						color: #007cff;
					}

					.order-no {
						font-weight: bold;
					}

					.label {
						color: #888;
					}
				}
			}

			.template-list {
				flex: 1;
				height: 0;
				overflow-y: auto;
				background-color: #fff;
				border-radius: 8rpx;
				box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.05);
				box-sizing: border-box;
				padding: 24rpx;
				display: flex;
				flex-direction: column;
				row-gap: 48rpx;

				.order-module {
					display: flex;
					align-items: flex-start;
					font-size: 24rpx;
					flex-direction: column;
					row-gap: 8rpx;
				}

				.template {
					font-size: 24rpx;

					.title {
						font-weight: bold;
					}

					.field-list {
						display: flex;
						flex-direction: column;

						.field {
							display: flex;
							flex-direction: column;
							border-bottom: 2rpx solid rgba(0, 0, 0, 0.1);

							.field-content {
								display: flex;
								justify-content: space-between;
								align-items: center;
								min-height: 72rpx;
								height: fit-content;
								column-gap: 24rpx;

								.label {
									height: 100%;
									display: flex;
									align-items: center;
									color: #606266;
								}

								.value {
									flex: 1;
									width: 0;
									height: 100%;
									display: flex;
									align-items: center;
									justify-content: flex-end;

									.input {
										font-size: 24rpx;
										width: 100%;
										text-align: right;

										:deep(.uni-input-input) {
											text-align: right;
										}
									}

									:deep(.uni-date) {
										width: unset !important;
										flex: unset !important;
									}

									.multiple-select {
										display: flex;
										align-items: center;
										color: gray;
										column-gap: 12rpx;
									}

									.select {
										display: flex;
										align-items: center;
										color: gray;
										column-gap: 12rpx;
										flex: 1;
										width: 0;
										justify-content: flex-end;

										:deep(.uni-select) {
											border: none !important;
											padding: 0;

											.uni-select__input-box {
												display: flex;
												column-gap: 12rpx;

												.uni-select__input-text {
													text-align: right;
												}
											}

											.uni-select__selector {
												width: fit-content;
												left: unset;
												right: 0;

												.uni-popper__arrow {
													left: unset !important;
													right: 10%;
												}

												.uni-select__selector-scroll {
													width: fit-content;

													.uni-scroll-view {
														width: fit-content;

														.uni-scroll-view-content {
															width: fit-content;
															white-space: nowrap;

															.uni-select__selector-item {
																justify-content: flex-end;
																width: fit-content;
																white-space: nowrap !important;

																text {
																	white-space: nowrap;
																}
															}
														}
													}

													.uni-select__selector-item {
														justify-content: flex-end;
														width: fit-content;
														white-space: nowrap !important;

														text {
															white-space: nowrap;
														}
													}
												}
											}
										}
									}

									.file-upload {
										color: #007cff;
										font-size: 24rpx;
									}
								}
							}

							.file-list {
								display: flex;
								gap: 6px;
								margin-bottom: 12rpx;
								flex-wrap: wrap;

								.file {
									width: 120rpx;
									height: 120rpx;
									box-sizing: border-box;
									border: 2rpx solid rgba(0, 0, 0, 0.1);
									display: flex;
									justify-content: center;
									align-items: center;
									position: relative;

									.img,
									.video {
										width: calc(100% - 24rpx);
										height: calc(100% - 24rpx);

										:deep(.video) {
											width: calc(100% - 24rpx) !important;
											height: calc(100% - 24rpx) !important;
										}
									}

									.del-btn {
										position: absolute;
										top: 0;
										right: 0;
										background-color: rgba(0, 0, 0, 0.4);
										width: 36rpx;
										height: 36rpx;
										display: flex;
										justify-content: center;
										align-items: center;
									}
								}
							}
						}
					}
				}
			}
		}

		.btn-container {
			padding: 30rpx 48rpx 30rpx;
			background-color: #fff;
			border-top: 1px solid #eee;

			:deep(button:after) {
				border: none !important;
			}

			.btn_bor {
				width: 100%;
				font-size: 28rpx;
				font-weight: bold;
				border-radius: 50rpx;
				background-color: #007cff;
				height: 80rpx;
				display: flex;
				align-items: center;
				justify-content: center;
			}
		}
	}
</style>
